#include "blockqueue.hpp"
#include "task.hpp"
#include <ctime>
#include <sys/types.h>
#include <unistd.h>


template<class C,class S>
class BlockQueues
{
public:
    BlockQueue<C>* c_bq;
    BlockQueue<S>* s_bq;
};
void *consumer(void *bqs_)
{
    BlockQueue<CalTask> *bq = (static_cast<BlockQueues<CalTask,SaveTask> *>(bqs_))->c_bq;
    BlockQueue<SaveTask> *save_bq = (static_cast<BlockQueues<CalTask,SaveTask> *>(bqs_))->s_bq;
    while (true)
    {
        CalTask t;
        bq->pop(&t);
        std::string result = t();
        printf("cal thread , 完成计算任务 : %s...done\n", result.c_str());
        SaveTask save(result,Save);
        save_bq->push(save);
        printf("cal thread , 推送存储任务完成...\n");
    }
    return nullptr;
}
void *productor(void *bqs_)
{
    BlockQueue<CalTask> *bq = (static_cast<BlockQueues<CalTask,SaveTask> *>(bqs_))->c_bq;
    while (true)
    {
        int x = rand() % 10 + 1;
        int y = rand() % 5;
        int operCode = rand() % oper.size();
        CalTask t(x, y, oper[operCode],mymath);
        bq->push(t);
        printf("productor thread , 生产计算任务 : %s\n",t.toTaskString().c_str());
        sleep(1);
    }
    return nullptr;
}
void* saver(void* bqs_)
{
    BlockQueue<SaveTask> *save_bq = (static_cast<BlockQueues<CalTask,SaveTask> *>(bqs_))->s_bq;
    while(true)
    {
        SaveTask t;
        save_bq->pop(&t);
        t();
        printf("save thread , 保存任务完成...\n");
    }
    return nullptr;
}
void test()
{
    srand((unsigned long)time(nullptr) ^ getpid());
    BlockQueues<CalTask,SaveTask> bqs;
    bqs.c_bq = new BlockQueue<CalTask>();
    bqs.s_bq = new BlockQueue<SaveTask>();
    pthread_t c, p, s;
    pthread_create(&p, nullptr, productor, &bqs);
    pthread_create(&c, nullptr, consumer, &bqs);
    pthread_create(&s, nullptr, saver, &bqs);
    pthread_join(p, nullptr);
    pthread_join(c, nullptr);
    pthread_join(s, nullptr);
    delete bqs.c_bq;
    delete bqs.s_bq;
}
int main()
{
    test();
    return 0;
}